using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using OfficeOpenXml;

namespace Tools.Controllers
{
    [ApiController]
    [Route("api")]
    public class UnifiedApiController : ControllerBase
    {
        private readonly ILogger<UnifiedApiController> _logger;
        private readonly IWebHostEnvironment _environment;
        private static readonly ConcurrentDictionary<string, ConversionTask> _conversionTasks = new();
        private static readonly ConcurrentDictionary<string, UploadedFile> _uploadedFiles = new();

        public UnifiedApiController(ILogger<UnifiedApiController> logger, IWebHostEnvironment environment)
        {
            _logger = logger;
            _environment = environment;
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
        }

        #region 文件上传

        [HttpPost("fileupload/single")]
        public async Task<IActionResult> UploadFile([FromForm] IFormFile file, [FromForm] string conversionType, [FromForm] int? splitCount = null)
        {
            try
            {
                if (file == null || file.Length == 0)
                {
                    return BadRequest(new { success = false, message = "请选择要上传的文件" });
                }

                // 验证文件类型
                var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
                if (fileExtension != ".xlsx" && fileExtension != ".xls")
                {
                    return BadRequest(new { success = false, message = "仅支持.xlsx和.xls格式的Excel文件" });
                }

                // 验证文件大小（100MB）
                if (file.Length > 100 * 1024 * 1024)
                {
                    return BadRequest(new { success = false, message = "文件大小不能超过100MB" });
                }

                // 生成文件ID
                string fileId = Guid.NewGuid().ToString();

                // 保存文件到内存
                using var memoryStream = new MemoryStream();
                await file.CopyToAsync(memoryStream);
                
                var uploadedFile = new UploadedFile
                {
                    Id = fileId,
                    FileName = file.FileName,
                    ContentType = file.ContentType,
                    FileSize = file.Length,
                    FileContent = memoryStream.ToArray(),
                    ConversionType = conversionType,
                    SplitCount = splitCount, // 保存拆分条数
                    UploadTime = DateTime.Now
                };

                _uploadedFiles[fileId] = uploadedFile;

                _logger.LogInformation($"文件上传成功: {file.FileName}, FileId: {fileId}, ConversionType: {conversionType}");

                return Ok(new
                {
                    success = true,
                    message = "文件上传成功",
                    fileId = fileId,
                    fileName = file.FileName,
                    fileSize = file.Length
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "文件上传失败");
                return StatusCode(500, new { success = false, message = $"文件上传失败: {ex.Message}" });
            }
        }

        #endregion

        #region 数据转换

        [HttpPost("dataconversion/start")]
        public IActionResult StartConversion([FromBody] ConversionRequest request)
        {
            try
            {
                if (!_uploadedFiles.TryGetValue(request.FileId, out var uploadedFile))
                {
                    return BadRequest(new { success = false, message = "文件不存在，请重新上传" });
                }

                // 生成任务ID
                string taskId = Guid.NewGuid().ToString();

                var task = new ConversionTask
                {
                    Id = taskId,
                    FileId = request.FileId,
                    ConversionType = request.ConversionType,
                    Status = "processing",
                    Progress = 0,
                    StartTime = DateTime.Now
                };

                _conversionTasks[taskId] = task;

                _logger.LogInformation($"开始转换任务: TaskId: {taskId}, ConversionType: {request.ConversionType}");

                // 在后台异步执行转换
                _ = Task.Run(async () => await ProcessConversionAsync(taskId, uploadedFile));

                return Ok(new
                {
                    success = true,
                    message = "转换任务已创建",
                    taskId = taskId
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "启动转换失败");
                return StatusCode(500, new { success = false, message = $"启动转换失败: {ex.Message}" });
            }
        }

        [HttpGet("dataconversion/progress/{taskId}")]
        public IActionResult GetConversionProgress(string taskId)
        {
            try
            {
                if (!_conversionTasks.TryGetValue(taskId, out var task))
                {
                    return NotFound(new { success = false, message = "转换任务不存在" });
                }

                return Ok(new
                {
                    success = true,
                    status = task.Status,
                    progress = task.Progress,
                    message = task.Message,
                    result = task.Result
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取转换进度失败: {taskId}");
                return StatusCode(500, new { success = false, message = $"获取转换进度失败: {ex.Message}" });
            }
        }

        [HttpGet("download/result/{taskId}/converted")]
        public IActionResult DownloadResult(string taskId)
        {
            try
            {
                if (!_conversionTasks.TryGetValue(taskId, out var task))
                {
                    return NotFound(new { success = false, message = "转换任务不存在" });
                }

                if (task.Status != "completed" || task.ResultFileContent == null)
                {
                    return BadRequest(new { success = false, message = "转换结果不可用" });
                }

                // 根据转换类型返回不同的MIME类型
                var uploadedFile = _uploadedFiles.Values.FirstOrDefault(f => f.Id == task.FileId);
                string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                
                if (uploadedFile?.ConversionType == "data-split")
                {
                    contentType = "application/zip";
                }

                return File(
                    task.ResultFileContent,
                    contentType,
                    task.ResultFileName ?? "转换结果.xlsx"
                );
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"下载转换结果失败: {taskId}");
                return StatusCode(500, new { success = false, message = $"下载转换结果失败: {ex.Message}" });
            }
        }

        #endregion

        #region 统计数据API

        [HttpGet("dashboard/stats")]
        public IActionResult GetDashboardStats()
        {
            try
            {
                // 计算今日统计数据
                var today = DateTime.Today;
                var todayTasks = _conversionTasks.Values.Where(t => t.StartTime.Date == today).ToList();
                var todayUploads = _uploadedFiles.Values.Where(f => f.UploadTime.Date == today).Count();
                
                // 计算总体统计
                var totalTasks = _conversionTasks.Values.Count;
                var completedTasks = _conversionTasks.Values.Where(t => t.Status == "completed").Count();
                var failedTasks = _conversionTasks.Values.Where(t => t.Status == "failed").Count();
                var processingTasks = _conversionTasks.Values.Where(t => t.Status == "processing").Count();
                
                var successRate = totalTasks > 0 ? (double)completedTasks / totalTasks * 100 : 100.0;

                var stats = new
                {
                    todayUploads = todayUploads,
                    todayConversions = todayTasks.Count,
                    successRate = Math.Round(successRate, 1),
                    pendingErrors = failedTasks,
                    totalTasks = totalTasks,
                    completedTasks = completedTasks,
                    failedTasks = failedTasks,
                    processingTasks = processingTasks
                };

                return Ok(new { success = true, data = stats });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取工作台统计数据失败");
                return StatusCode(500, new { success = false, message = $"获取统计数据失败: {ex.Message}" });
            }
        }

        [HttpGet("dashboard/recent-activities")]
        public IActionResult GetRecentActivities()
        {
            try
            {
                var recentTasks = _conversionTasks.Values
                    .OrderByDescending(t => t.StartTime)
                    .Take(10)
                    .Select(t => new
                    {
                        id = t.Id,
                        type = GetActivityType(t.Status, t.ConversionType),
                        title = GetActivityTitle(t.Status, t.ConversionType),
                        time = GetRelativeTime(t.StartTime),
                        status = t.Status,
                        timestamp = t.StartTime
                    })
                    .ToList();

                return Ok(new { success = true, data = recentTasks });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取最近活动失败");
                return StatusCode(500, new { success = false, message = $"获取最近活动失败: {ex.Message}" });
            }
        }

        [HttpGet("dashboard/conversion-trend")]
        public IActionResult GetConversionTrend()
        {
            try
            {
                // 获取过去7天的转换数据
                var past7Days = Enumerable.Range(0, 7)
                    .Select(i => DateTime.Today.AddDays(-i))
                    .Reverse()
                    .ToList();

                var trendData = past7Days.Select(date => new
                {
                    date = date.ToString("MM-dd"),
                    conversions = _conversionTasks.Values.Count(t => t.StartTime.Date == date),
                    successful = _conversionTasks.Values.Count(t => t.StartTime.Date == date && t.Status == "completed"),
                    failed = _conversionTasks.Values.Count(t => t.StartTime.Date == date && t.Status == "failed")
                }).ToList();

                return Ok(new { success = true, data = trendData });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取转换趋势数据失败");
                return StatusCode(500, new { success = false, message = $"获取转换趋势数据失败: {ex.Message}" });
            }
        }

        [HttpPost("dashboard/seed-data")]
        public IActionResult SeedTestData()
        {
            try
            {
                // 清空现有数据
                _conversionTasks.Clear();
                _uploadedFiles.Clear();

                var random = new Random();
                var now = DateTime.Now;

                // 生成模拟文件上传记录
                var conversionTypes = new[] { "yinhai-to-ph1", "clinic-log", "ph3-remote", "data-split" };
                var fileNames = new[] 
                {
                    "银海品项数据.xlsx", "门诊日志.xlsx", "PH3异地数据.xlsx", "数据拆分文件.xlsx",
                    "品项信息表.xlsx", "日志数据.xlsx", "异地结算.xlsx", "大数据文件.xlsx"
                };

                // 生成过去7天的数据
                for (int day = 0; day < 7; day++)
                {
                    var date = DateTime.Today.AddDays(-day);
                    var dayTaskCount = random.Next(5, 20); // 每天5-20个任务

                    for (int i = 0; i < dayTaskCount; i++)
                    {
                        var fileId = Guid.NewGuid().ToString();
                        var taskId = Guid.NewGuid().ToString();
                        var conversionType = conversionTypes[random.Next(conversionTypes.Length)];
                        var fileName = fileNames[random.Next(fileNames.Length)];
                        var startTime = date.AddHours(random.Next(8, 18)).AddMinutes(random.Next(0, 59));

                        // 模拟文件上传
                        var uploadedFile = new UploadedFile
                        {
                            Id = fileId,
                            FileName = fileName,
                            ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                            FileSize = random.Next(100000, 10000000), // 100KB - 10MB
                            FileContent = new byte[1000], // 模拟数据
                            ConversionType = conversionType,
                            UploadTime = startTime.AddMinutes(-random.Next(1, 10))
                        };
                        _uploadedFiles[fileId] = uploadedFile;

                        // 模拟转换任务
                        var status = random.NextDouble() < 0.85 ? "completed" : (random.NextDouble() < 0.8 ? "failed" : "processing");
                        var task = new ConversionTask
                        {
                            Id = taskId,
                            FileId = fileId,
                            ConversionType = conversionType,
                            Status = status,
                            Progress = status == "completed" ? 100 : (status == "processing" ? random.Next(10, 90) : 0),
                            Message = status == "completed" ? "转换完成" : (status == "failed" ? "转换失败" : "正在处理"),
                            StartTime = startTime,
                            EndTime = status != "processing" ? startTime.AddMinutes(random.Next(1, 30)) : null
                        };

                        if (status == "completed")
                        {
                            task.ResultFileContent = new byte[1000];
                            task.ResultFileName = GenerateResultFileName(fileName, conversionType == "data-split" ? ".zip" : ".xlsx");
                            task.Result = new
                            {
                                stats = new
                                {
                                    successful = random.Next(800, 1000),
                                    failed = random.Next(0, 50),
                                    total = random.Next(850, 1000)
                                }
                            };
                        }

                        _conversionTasks[taskId] = task;
                    }
                }

                _logger.LogInformation("模拟数据生成完成");
                return Ok(new { success = true, message = "模拟数据生成完成", 
                    totalFiles = _uploadedFiles.Count, totalTasks = _conversionTasks.Count });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成模拟数据失败");
                return StatusCode(500, new { success = false, message = $"生成模拟数据失败: {ex.Message}" });
            }
        }

        #endregion

        #region 私有辅助方法

        private string GetActivityType(string status, string conversionType)
        {
            return status switch
            {
                "completed" => "success",
                "failed" => "danger",
                "processing" => "info",
                _ => "secondary"
            };
        }

        private string GetActivityTitle(string status, string conversionType)
        {
            var typeName = conversionType switch
            {
                "yinhai-to-ph1" => "银海转PH1",
                "clinic-log" => "门诊日志转换",
                "ph3-remote" => "PH3异地数据转换",
                "data-split" => "数据拆分",
                _ => "数据转换"
            };

            return status switch
            {
                "completed" => $"{typeName}完成",
                "failed" => $"{typeName}失败",
                "processing" => $"{typeName}进行中",
                _ => $"{typeName}状态未知"
            };
        }

        private string GetRelativeTime(DateTime dateTime)
        {
            var timeSpan = DateTime.Now - dateTime;
            
            if (timeSpan.TotalMinutes < 1)
                return "刚刚";
            if (timeSpan.TotalMinutes < 60)
                return $"{(int)timeSpan.TotalMinutes}分钟前";
            if (timeSpan.TotalHours < 24)
                return $"{(int)timeSpan.TotalHours}小时前";
            if (timeSpan.TotalDays < 7)
                return $"{(int)timeSpan.TotalDays}天前";
            
            return dateTime.ToString("MM-dd HH:mm");
        }

        /// <summary>
        /// 生成结果文件名：原文件名 + 年月日
        /// </summary>
        /// <param name="originalFileName">原文件名</param>
        /// <param name="extension">文件扩展名</param>
        /// <returns>新的文件名</returns>
        private string GenerateResultFileName(string originalFileName, string extension = ".xlsx")
        {
            try
            {
                // 获取不带扩展名的原文件名
                var nameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
                
                // 生成年月日格式
                var dateString = DateTime.Now.ToString("yyyyMMdd");
                
                // 组合文件名：原文件名 + 年月日 + 扩展名
                var resultFileName = $"{nameWithoutExtension}_{dateString}{extension}";
                    
                return resultFileName;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, $"生成结果文件名失败，使用默认名称: {originalFileName}");
                
                // 如果生成失败，返回默认名称
                var dateString = DateTime.Now.ToString("yyyyMMdd");
                return $"转换结果_{dateString}{extension}";
            }
        }

        #endregion

        #region 私有方法

        private async Task ProcessConversionAsync(string taskId, UploadedFile uploadedFile)
        {
            try
            {
                var task = _conversionTasks[taskId];
                task.Progress = 10;
                task.Message = "正在初始化转换...";

                // 创建临时文件用于处理
                using var inputStream = new MemoryStream(uploadedFile.FileContent);
                var tempFile = new FormFile(inputStream, 0, uploadedFile.FileContent.Length, "file", uploadedFile.FileName)
                {
                    Headers = new HeaderDictionary(),
                    ContentType = uploadedFile.ContentType
                };

                task.Progress = 30;
                task.Message = "正在执行数据转换...";

                byte[] resultContent = null;
                string resultFileName = null;

                // 根据转换类型调用对应的处理逻辑
                switch (uploadedFile.ConversionType)
                {
                    case "yinhai-to-ph1":
                        var importLogger = _logger as ILogger<ImportController> ?? 
                            Microsoft.Extensions.Logging.Abstractions.NullLogger<ImportController>.Instance;
                        var importController = new ImportController(_environment, importLogger);
                        var result1 = await importController.ImportYHToPH1(tempFile);
                        if (result1 is FileContentResult fileContentResult1)
                        {
                            resultContent = fileContentResult1.FileContents;
                            resultFileName = GenerateResultFileName(uploadedFile.FileName, ".xlsx");
                        }
                        break;

                    case "clinic-log":
                        var ph2Logger = _logger as ILogger<Ph2LogController> ?? 
                            Microsoft.Extensions.Logging.Abstractions.NullLogger<Ph2LogController>.Instance;
                        var ph2Controller = new Ph2LogController(_environment, ph2Logger);
                        var result2 = await ph2Controller.ImportPh2Log(tempFile);
                        if (result2 is FileContentResult fileContentResult2)
                        {
                            resultContent = fileContentResult2.FileContents;
                            resultFileName = GenerateResultFileName(uploadedFile.FileName, ".xlsx");
                        }
                        break;

                    case "ph3-remote":
                        var ph3Logger = _logger as ILogger<ImportPh3Controller> ?? 
                            Microsoft.Extensions.Logging.Abstractions.NullLogger<ImportPh3Controller>.Instance;
                        var ph3Controller = new ImportPh3Controller(_environment, ph3Logger);
                        var result3 = await ph3Controller.ImportPh3Data(tempFile);
                        if (result3 is FileContentResult fileContentResult3)
                        {
                            resultContent = fileContentResult3.FileContents;
                            resultFileName = GenerateResultFileName(uploadedFile.FileName, ".xlsx");
                        }
                        break;

                    case "data-split":
                        var splitLogger = _logger as ILogger<DataSplitController> ?? 
                            Microsoft.Extensions.Logging.Abstractions.NullLogger<DataSplitController>.Instance;
                        var splitController = new DataSplitController(splitLogger);
                        // 使用用户指定的拆分条数，默认500条
                        var splitCount = uploadedFile.SplitCount ?? 500;
                        var result4 = await splitController.SplitData(tempFile, splitCount);
                        if (result4 is FileContentResult fileContentResult4)
                        {
                            resultContent = fileContentResult4.FileContents;
                            resultFileName = GenerateResultFileName(uploadedFile.FileName, ".zip");
                        }
                        break;

                    default:
                        throw new NotSupportedException($"不支持的转换类型: {uploadedFile.ConversionType}");
                }

                if (resultContent == null)
                {
                    throw new InvalidOperationException("转换失败，未生成结果文件");
                }

                task.Progress = 90;
                task.Message = "正在生成结果文件...";

                // 保存结果
                task.ResultFileContent = resultContent;
                task.ResultFileName = resultFileName;
                task.Progress = 100;
                task.Status = "completed";
                task.Message = "转换完成";
                task.EndTime = DateTime.Now;

                // 生成统计信息
                task.Result = new
                {
                    stats = new
                    {
                        successful = 1, // 这里应该根据实际转换情况计算
                        failed = 0,
                        total = 1
                    }
                };

                _logger.LogInformation($"转换任务完成: TaskId: {taskId}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"转换任务失败: TaskId: {taskId}");
                
                var task = _conversionTasks[taskId];
                task.Status = "failed";
                task.Message = $"转换失败: {ex.Message}";
                task.EndTime = DateTime.Now;
            }
        }

        #endregion

        #region 配置相关API

        [HttpGet("config")]
        public IActionResult GetConfig()
        {
            try
            {
                var config = new
                {
                    conversionTypes = new
                    {
                        yinhai_to_ph1 = new
                        {
                            name = "银海品项转PH1",
                            description = "银海品项格式转换为PH1系统数据",
                            sourceFormat = "银海品项",
                            targetFormat = "PH1"
                        },
                        clinic_log = new
                        {
                            name = "门诊日志转换",
                            description = "支持任意表格导入的门诊日志转换",
                            sourceFormat = "任意格式",
                            targetFormat = "标准门诊日志"
                        },
                        ph3_remote = new
                        {
                            name = "PH3异地数据转换",
                            description = "PH3异地就医数据转换处理",
                            sourceFormat = "PH3异地",
                            targetFormat = "JY结算记录"
                        },
                        data_split = new
                        {
                            name = "数据拆分",
                            description = "将大型Excel文件拆分为多个小文件",
                            sourceFormat = "Excel文件",
                            targetFormat = "多个拆分文件"
                        }
                    }
                };

                return Ok(config);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取配置失败");
                return StatusCode(500, new { success = false, message = $"获取配置失败: {ex.Message}" });
            }
        }

        #endregion
    }

    #region 数据模型

    public class ConversionRequest
    {
        public string FileId { get; set; } = string.Empty;
        public string ConversionType { get; set; } = string.Empty;
        public Dictionary<string, object> BusinessRules { get; set; } = new();
    }

    public class UploadedFile
    {
        public string Id { get; set; } = string.Empty;
        public string FileName { get; set; } = string.Empty;
        public string ContentType { get; set; } = string.Empty;
        public long FileSize { get; set; }
        public byte[] FileContent { get; set; } = Array.Empty<byte>();
        public string ConversionType { get; set; } = string.Empty;
        public int? SplitCount { get; set; } // 数据拆分条数，仅在data-split类型时使用
        public DateTime UploadTime { get; set; }
    }

    public class ConversionTask
    {
        public string Id { get; set; } = string.Empty;
        public string FileId { get; set; } = string.Empty;
        public string ConversionType { get; set; } = string.Empty;
        public string Status { get; set; } = string.Empty; // processing, completed, failed
        public int Progress { get; set; } // 0-100
        public string Message { get; set; } = string.Empty;
        public DateTime StartTime { get; set; }
        public DateTime? EndTime { get; set; }
        public object? Result { get; set; }
        public byte[]? ResultFileContent { get; set; }
        public string? ResultFileName { get; set; }
    }

    #endregion
}